# path marcros
SRC_PATH := ./src
OBJ_PATH := ./obj
BIN_PATH := ./bin
#debug := 1
ifdef release
DBGFLAG := 
else 
DBGFLAG := -g -O0
endif  

# 编译命令
CC := g++
AR := ar

# -fvisibility=hidden 隐藏导出符号
CCFLAG := -Wall -fvisibility=hidden -std=c++11 -fPIC
CCOBJFLAG := $(CCFLAG) -Wconversion-null -Wunused-function -c

# -Wl,--exclude-libs,ALL 隐藏静态库的导出符号
LINKFLAG := -Wl,--exclude-libs,ALL -Wl,-Bstatic -L./lib -Wl,-Bdynamic -ldl -lrt -lpthread

# 目标文件
TARGETBIN 	:= ${BIN_PATH}/main
TARGETLIBA 	:= ${BIN_PATH}/main.a
TARGETLIBSO	:= ${BIN_PATH}/main.so

# 头文件
PUBLICINC := -I./include
INCLUDPATH := $(PUBLICINC) -I./src/

# cpp和c源文件
DIRS := $(shell ls $(SRC_PATH) -R | grep '^\./.*:$$' | awk '{gsub(":","");print}')
CSRC := $(foreach dir, $(DIRS), $(wildcard $(dir)/*.c))
CPPSRC := $(foreach dir, $(DIRS), $(wildcard $(dir)/*.cpp))
# $(warning DIRS=$(DIRS))
$(warning CSRC=$(CSRC))
$(warning CPPSRC=$(CPPSRC))

# cpp和c目标生成文件
OBJDIRS := $(DIRS:$(SRC_PATH)%=$(OBJ_PATH)%)
COBJS := $(patsubst %.c,%.o,$(CSRC:$(SRC_PATH)%=$(OBJ_PATH)%) )  
CPPOBJS := $(patsubst %.cpp,%.o,$(CPPSRC:$(SRC_PATH)%=$(OBJ_PATH)%) )  
# $(warning OBJDIRS=$(OBJDIRS))
$(warning COBJS=$(COBJS))
$(warning CPPOBJS=$(CPPOBJS))

# clean files list
DISTCLEAN_LIST := $(COBJS) $(CPPOBJS)

CLEAN_LIST := $(TARGETCMD) \
			$(TARGETMASTER) \
			$(DISTCLEAN_LIST)

# default rule
default: bin

path:
	$(foreach dir, $(OBJDIRS), $$(test -d $(dir) || mkdir -p $(dir)))
	test -d $(OBJ_PATH) || mkdir -p $(OBJ_PATH)
	test -d $(BIN_PATH) || mkdir -p $(BIN_PATH)

$(OBJ_PATH)/%.o:$(SRC_PATH)/%.cpp
	$(CC) $(CCOBJFLAG) $(DBGFLAG) $(INCLUDPATH) $< -o $@

$(OBJ_PATH)/%.o:$(SRC_PATH)/%.c
	$(CC) $(CCOBJFLAG) $(DBGFLAG) $(INCLUDPATH) $< -o $@	

target:$(TARGETBIN)
$(TARGETBIN): $(CPPOBJS) $(COBJS)
	$(CC) $(CCFLAG) $(DBGFLAG) $^ -o $@ $(LINKFLAG)
	
targeta:$(TARGETLIBA)
$(TARGETLIBA): $(CPPOBJS) $(COBJS)
	$(AR) rcs $@ $^
	
targetso:$(TARGETLIBSO)
$(TARGETLIBSO): $(CPPOBJS) $(COBJS)
	$(CC) -shared -fPIC $^ -o $@ $(LINKFLAG)

.PHONY: bin 
bin: path target

.PHONY: liba 
liba: path targeta

.PHONY: libso 
libso: path targetso

.PHONY: clean
clean:
	@echo CLEAN $(CLEAN_LIST)
	@rm -f $(CLEAN_LIST)
	@rm -rf $(OBJ_PATH)

.PHONY: distclean
distclean:
	@echo CLEAN $(CLEAN_LIST)
	@rm -f $(DISTCLEAN_LIST)
	@rm -rf $(OBJ_PATH)
	
.PHONY: force
force: clean all